/*
 * <h3>Title:wheel-utils系统</h3>
 * <p>Copyright (c) 2019, wnfbx@163.com. All rights reserved.</p>
 * @author wnfbx@163.com
 */
package wang.naifei.core.utils.io;

import wang.naifei.core.utils.Assert;
import wang.naifei.core.utils.StringUtils;

import java.io.*;

/**
 * <dt>Description:IOUtil</dt>
 * <dd>IO工具类</dd>
 * <dd>author: wnfbx@163.com</dd>
 * <dd>version:1.0 <i>2022/1/14 23:48</i></dd>
 *
 * @since jdk1.7+
 */
public class IOUtil {

    /**
     * <dt>Description:copy</dt>
     * <dd>复制流</dd>
     * <dd>author: wnfbx@163.com</dd>
     * <dd>version:1.0 <i>2022/1/15 1:01</i></dd>
     *
     * @param input  输入
     * @param output 输出
     * @param buffer 缓冲
     * @since jdk1.7+
     */
    public static void copy(InputStream input, OutputStream output, byte[] buffer) throws IOException {
        int len;
        while ((len = input.read(buffer)) != -1) {
            output.write(buffer, 0, len);
        }
    }

    /**
     * <dt>Description:copy</dt>
     * <dd>复制流,4k缓存</dd>
     * <dd>author: wnfbx@163.com</dd>
     * <dd>version:1.0 <i>2022/1/15 1:19</i></dd>
     *
     * @param input  输入
     * @param output 输出
     * @since jdk1.7+
     */
    public static void copy(InputStream input, OutputStream output) throws IOException {
        copy(input, output, new byte[4096]);
    }

    /**
     * <dt>Description:copy</dt>
     * <dd>复制读写</dd>
     * <dd>author: wnfbx@163.com</dd>
     * <dd>version:1.0 <i>2022/1/15 1:54</i></dd>
     *
     * @param reader 读
     * @param writer 写
     * @param buffer 缓冲
     * @since jdk1.7+
     */
    public static void copy(Reader reader, Writer writer, char[] buffer) throws IOException {
        int len;
        while ((len = reader.read(buffer)) != -1) {
            writer.write(buffer, 0, len);
        }
    }

    /**
     * <dt>Description:copy</dt>
     * <dd>复制读写，默认缓冲</dd>
     * <dd>author: wnfbx@163.com</dd>
     * <dd>version:1.0 <i>2022/1/15 1:55</i></dd>
     *
     * @param reader 读
     * @param writer 写
     * @since jdk1.7+
     */
    public static void copy(Reader reader, Writer writer) throws IOException {
        copy(reader, writer, new char[4096]);
    }

    /**
     * <dt>Description:copy</dt>
     * <dd>分片复制</dd>
     * <dd>author: wnfbx@163.com</dd>
     * <dd>version:1.0 <i>2022/1/15 0:23</i></dd>
     *
     * @param inputStream   输入
     * @param outputStream  输出
     * @param offset        偏移
     * @param contentLength 内容长度
     * @param byteLength    缓存长度
     * @since jdk1.7+
     */
    public static void copy(InputStream inputStream, OutputStream outputStream, long offset, long contentLength, int byteLength) {
        Assert.notNull(inputStream, "inputStream must not be null");
        Assert.notNull(outputStream, "outputStream must not be null");
        byteLength = byteLength > 0 ? byteLength : 4096;

        try {
            if (offset > 0L) {
                long skip = inputStream.skip(offset);
                if (skip < offset) {//实际跳过数量小于offset，表示offset 超限
                    //throw new ArrayIndexOutOfBoundsException("offset out of Bounds");
                    return;
                }
            }
            byte[] b = new byte[byteLength];
            int len;

            if (contentLength > 0L) {
                while (contentLength > 0L) {
                    len = inputStream.read(b, 0, (int) Math.min(contentLength, byteLength));
                    outputStream.write(b, 0, len);
                    contentLength -= len;
                }
            } else {
                copy(inputStream, outputStream, b);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            flushAndCloseQuietly(inputStream, outputStream);
        }
    }

    /**
     * <dt>Description:toString</dt>
     * <dd>input 转 String</dd>
     * <dd>author: wnfbx@163.com</dd>
     * <dd>version:1.0 <i>2022/1/15 1:42</i></dd>
     *
     * @param input   输入
     * @param charset 字符集
     * @return java.lang.String
     * @since jdk1.7+
     */
    public static String toString(InputStream input, String charset) throws IOException {
        ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
        copy(input, swapStream);
        return swapStream.toString(charset);
    }

    /**
     * <dt>Description:toString</dt>
     * <dd>input 转 String UTF-8字符集</dd>
     * <dd>author: wnfbx@163.com</dd>
     * <dd>version:1.0 <i>2022/1/15 2:02</i></dd>
     *
     * @param input 输入流
     * @return java.lang.String
     * @since jdk1.7+
     */
    public static String toString(InputStream input) throws IOException {
        return toString(input, "utf-8");
    }

    /**
     * <dt>Description:toString</dt>
     * <dd>reader to String</dd>
     * <dd>author: wnfbx@163.com</dd>
     * <dd>version:1.0 <i>2022/1/15 15:14</i></dd>
     *
     * @param reader
     * @return java.lang.String
     * @since jdk1.7+
     */
    public static String toString(Reader reader) throws IOException {
        BufferedReader bufferedReader = new BufferedReader(reader);
        StringBuffer sb = new StringBuffer();
        String temp;
        while ((temp = bufferedReader.readLine()) != null) {
            sb.append(temp);
        }
        closeQuietly(bufferedReader);
        return sb.toString();
    }

    /**
     * <dt>Description:inputStreanToByte</dt>
     * <dd>流转byte</dd>
     * <dd>author: wnfbx@163.com</dd>
     * <dd>version:1.0 <i>2022/1/15 2:42</i></dd>
     *
     * @param input 输入
     * @return byte[]
     * @since jdk1.7+
     */
    public static byte[] toByte(InputStream input) throws IOException {
        ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
        copy(input, swapStream);
        return swapStream.toByteArray();
    }

    /**
     * <dt>Description:flushAndCloseQuietly</dt>
     * <dd>静默关闭</dd>
     * <dd>author: wnfbx@163.com</dd>
     * <dd>version:1.0 <i>2022/1/15 1:24</i></dd>
     *
     * @param s 关闭的所有对象
     * @see Flushable
     * @since jdk1.7+
     */
    @SafeVarargs
    public static <T extends Closeable> void flushAndCloseQuietly(T... s) {
        if (s == null) {
            return;
        }
        for (T t : s) {
            if (t instanceof Flushable) {
                flashQuietly((Flushable) t);
            }
            closeQuietly(t);
        }
    }

    /**
     * <dt>Description:flashQuietly</dt>
     * <dd>静默刷新</dd>
     * <dd>author: wnfbx@163.com</dd>
     * <dd>version:1.0 <i>2022/1/15 1:27</i></dd>
     *
     * @param objects 可刷新对象
     * @since jdk1.7+
     */
    public static void flashQuietly(Flushable... objects) {
        if (objects != null) {
            for (Flushable flushable : objects) {
                try {
                    flushable.flush();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * <dt>Description:closeQuietly</dt>
     * <dd>静默关闭</dd>
     * <dd>author: wnfbx@163.com</dd>
     * <dd>version:1.0 <i>2022/1/15 1:27</i></dd>
     *
     * @param objects 关闭对象
     * @since jdk1.7+
     */
    public static void closeQuietly(Closeable... objects) {
        if (objects != null) {
            for (Closeable closeable : objects) {
                try {
                    closeable.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void fileWriteLine(File file, FileWriteLineObject... objects) throws IOException {
        try {
            FileReader fileReader = new FileReader(file);
            BufferedReader bufferedReader = new BufferedReader(fileReader);
            String line;
            StringBuffer sb = new StringBuffer();
            readLine:
            while ((line = bufferedReader.readLine()) != null) {
                for (FileWriteLineObject fileWriteLineObject : objects) {
                    if (fileWriteLineObject.filter.accept(line)) {
                        sb.append(fileWriteLineObject.replace).append(StringUtils.lineSeparator);
                        continue readLine;
                    }
                }
                sb.append(line).append(StringUtils.lineSeparator);
            }
            closeQuietly(fileReader, bufferedReader);

            FileWriter fileWriter = new FileWriter(file);
            BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
            bufferedWriter.write(sb.toString());
            closeQuietly(bufferedWriter, fileWriter);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }
}